package log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.LinkedList;

import serverClient.LogObserver;

public class Log implements LogObserver {

	private final boolean DEBUG = false;

	private File logFile;
	private boolean saveLog;
	private LinkedList<LogToGuiObserver> logToGuiObserverList;

	private FileOutputStream out; // Declare a file output object
	private PrintWriter pWriter; // Declare a print writer object
	private FileInputStream fStream;
	private BufferedReader in;

	public Log(String confDir, boolean saveLog) {

		logToGuiObserverList = new LinkedList<LogToGuiObserver>();

		logFile = new File(confDir + File.separator + "log.txt");
		this.saveLog = saveLog;
		openFileForWriting(this.saveLog); // Creates a file if it does not already exist, clears the file if saveLog is false
		closeWritingPart();
	}

	public void setSaveLog(boolean saveLog) {
		this.saveLog = saveLog;
		openFileForWriting(true); // Creates a file if it does not already exist
		closeWritingPart();
	}

	public String getLogLine() {
		String line;
		try {
			line = in.readLine();
		} catch (Exception e) {
			line = "Error reading from log file";
			if(DEBUG) System.err.println("Error reading from log file");
		}
		return line;
	}

	// Enters the string entry to the log.txt file
	public void makeEntry(String entry) {
		openFileForWriting(true);
		try {
			pWriter.println(entry);
		} catch (Exception e) {
			e.printStackTrace();
			if(DEBUG) System.err.println("Error writing to log file");
		}
		closeWritingPart();
	}

	public void clearLogFile() {
		if(DEBUG) System.out.println("Clearing log");
		openFileForWriting(false); // Clearing the log file by not appending when opening
		closeWritingPart();
	}

	// Opens the file, if append is true then for append otherwise the file will be read/written from the beginning
	private void openFileForWriting(boolean append) {
		try {
			out = new FileOutputStream(logFile, append);
			pWriter = new PrintWriter(out, true);
		} catch (Exception e) {
			if(DEBUG) System.err.println("File error on open for writing");
		}
	}

	private void closeWritingPart() {
		try {
			pWriter.close();
			out.close();
		} catch (Exception e) {
			if(DEBUG) System.err.println("File error on closing writing part");
		}
	}

	public void openFileForReading() {
		try {
			fStream = new FileInputStream(logFile);
			in = new BufferedReader(new InputStreamReader(fStream));
		} catch (Exception e) {
			if(DEBUG) System.err.println("File error on open for reading");
		}
	}

	public void closeReadingPart() {
		try {
			in.close();
			fStream.close();
		} catch (Exception e) {
			if(DEBUG) System.err.println("File error on closing reading part");
		}
	}


	// LogObserver methods //

	public void logMessage(String[] log) {
		// TODO Auto-generated method stub	
	}

	public void connectionStatusChanged(String message) {
		sendConnectionStatusChanged(message); // Send info to the GUI
	}

	public void connectionStatusWarning(String message) {
		sendConnectionStatusWarning(message); // Send info to the GUI
		message = message.split(";")[1] + " - " + message.split(";")[0];
		makeEntry(message);
	}

	public void transferMessage(String message) {
		sendTransferMessage(message); // Send info to the GUI
		// Simple filter
		if (!message.startsWith("Gathering data")) {
			message = message.split(";")[1] + " - " + message.split(";")[0];
			makeEntry(message);
		}
	}


	// LogToGuiObserver methods //

	public void addLogToGuiObserver(LogToGuiObserver o) {
		if (o != null) logToGuiObserverList.add(o);
	}
	
	private void sendConnectionStatusChanged(String message) {
		for (int i=0; i < logToGuiObserverList.size(); i++) {
			logToGuiObserverList.get(i).connectionStatusChanged(message);
		}		
	}
	
	private void sendConnectionStatusWarning(String message) {
		for (int i=0; i < logToGuiObserverList.size(); i++) {
			logToGuiObserverList.get(i).connectionStatusWarning(message);
		}		
	}
	
	private void sendTransferMessage(String message) {
		for (int i=0; i < logToGuiObserverList.size(); i++) {
			logToGuiObserverList.get(i).transferMessage(message);
		}		
	}
}
